import { IncomingMessage } from "http";
import RequestOption from "./request-option";

export = class Cookie {
  public static typeof: Cookie = new Cookie();

  /**
   * cookie树源数据
   */
  public cookieTree: {
    [key: string]: any
  } = {};

  /**
   * 封装cookie
   * @param url 
   * @returns 
   */
  public encapsulation(url: string) {
    const urlInfo = new URL(url);
    if (!this.cookieTree[urlInfo.hostname]) { return "" };
    let cookie = new Set();
    let cookieArr = [this.cookieTree[urlInfo.hostname]["/"] || {}];
    Object.keys(this.cookieTree[urlInfo.hostname]).forEach(e => {
      if (urlInfo.pathname.startsWith(e)) {
        cookieArr.push(this.cookieTree[urlInfo.hostname][e]);
      }
    })
    cookieArr.forEach(e => {
      Object.keys(e).forEach(key => {
        cookie.add(key + "=" + e[key]);
      })
    })
    return Array.from(cookie).join("; ");
  }

  public add(url: string, data: string): void;
  public add(url: string, data: IncomingMessage): void;
  public add(url: string, data: IncomingMessage | string, option: typeof RequestOption.typeof): void;
  public add(url: string, data: string | IncomingMessage, option?: typeof RequestOption.typeof): void {
    if (!data) return;
    let urlInfo = new URL(url);
    if (typeof data != 'string') {
      if (!data.headers["set-cookie"]) {
        return;
      }
      data.headers["set-cookie"]?.forEach((e: string) => {
        let key = e.match(/(?<=[Pp]ath=)[^;\n ]*/)?.[0] as string;
        if (!this.cookieTree[urlInfo.hostname]) {
          this.cookieTree[urlInfo.hostname] = {};
          this.cookieTree[urlInfo.hostname][key] = {};
        } else if (!this.cookieTree[urlInfo.hostname][key]) {
          this.cookieTree[urlInfo.hostname][key] = {};
        }
        let a = e.split("; ");
        a = a[0].split("=");
        this.cookieTree[urlInfo.hostname][key][a[0]] = a[1];
      })
    } else {
      let base = urlInfo.pathname.match(/^\/.*?[\/]?$/)?.[0] as string;
      if (!base.endsWith("/")) {
        base += "/";
      }
      // 从res = url 解析出路径
      if (!this.cookieTree[urlInfo.hostname]) { this.cookieTree[urlInfo.hostname] = {} }
      if (!this.cookieTree[urlInfo.hostname][base]) {
        this.cookieTree[urlInfo.hostname][base] = {};
      }
      // 解析cookie
      data.split("; ").forEach(e => {
        if (!e) return
        let a = e.split("=");
        this.cookieTree[urlInfo.hostname][base][a[0]] = a[1];
      })
    }

    if (option && option.headers) {
      option.headers.cookie = this.encapsulation(url);
    }
  }

  // 删除某个网址下指定path的所有cookie
  public delete(url: string) {
    let info = new URL(url);
    delete this.cookieTree[info.hostname][info.pathname];
  }

  /**
   * 清空 url路径下的cookie
   * @param url 
   */
  public empty(url: string) {
    delete this.cookieTree[(new URL(url)).hostname];
  }

  /**
   * 合并cookie树
   * @param cookie 
   */
  public mergeCookieTree(cookie: object) {
    if (!cookie) return;
    Object.keys(cookie).forEach(e => {
      if (this.cookieTree[e]) {
        // @ts-ignore
        this.cookieTree[e] = Object.assign(this.cookieTree[e], cookie[e]);
      } else {
        // @ts-ignore
        this.cookieTree[e] = cookie[e];
      }
    })
  }

  /**
   * 获取cookieTree
   */
  public getCookieTree() {
    return JSON.parse(JSON.stringify(this.cookieTree))
  }
}